package com.cskaoyan.aspect;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author stone
 * @date 2022/10/04 11:08
 */
@Component
@Aspect //@Component不省略
public class CustomAspect {

    // @Pointcut增加在方法上
    // 使用value属性作为切入点表达式
    // 方法名作为切入点的id
    @Pointcut("execution(* com.cskaoyan.service..*(..))")
    public void servicePointcut() {
    }

    // 通知和切入点的关系是通过通知注解的value属性来维护
    //  - 可以直接写切入点表达式
    //  - 通过切入点@Pointcut的方法名引用切入点,后面有一对括号不要漏掉了
    //@Before("execution(* com.cskaoyan.service..*(..))")
    @Before("servicePointcut()")
    public void serviceBefore(JoinPoint joinPoint) {
        System.out.println("Before通知在委托类方法执行之前会调用到");
    }

    @After("servicePointcut()")
    public void serviceAfter() {
        System.out.println("After通知对应的方法，类似于try-catch中的finally");
    }

    // 返回值 作为代理对象执行方法的返回值
    // JoinPoint连接点 → 获得通知执行过程中的一些特殊的值
    @Around("servicePointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();
        Object proxy = joinPoint.getThis();

        Signature signature = joinPoint.getSignature();
        String name = signature.getName();

        Object[] args = joinPoint.getArgs();

        if ("sayHello2".equals(name)) {
            if (args != null && args.length > 0) {
                args[0] = args[0] + "牛皮";
            }
        }

        System.out.println("around通知在委托类方法执行之 →前← 执行的内容");
        //Object proceed = joinPoint.proceed();
        Object proceed = joinPoint.proceed(args);
        System.out.println("around通知在委托类方法执行之 →后← 执行的内容");

        return proceed;
    }

    // afterReturning通知传入一个Object类型的形参，用来接收委托类方法返回的结果
    @AfterReturning(value = "servicePointcut()",returning = "result")
    public void afterReturning(Object result) {
        System.out.println("在return之后执行，并且可以获得return的结果：" + result);
    }

    //afterThrowing通知传入一个Exception（或Throwable）类型的形参，用来接收委托类方法抛出的异常
    @AfterThrowing(value = "servicePointcut()",throwing = "exception")
    public void afterThrowing(Exception exception) {
        System.out.println("在抛出异常之后执行，并且可以获得抛出的异常对象：" + exception.getMessage());
    }
}
